package reflect;

import org.junit.Test;

import java.lang.reflect.*;

/**
 * @Author wangzhipeng
 * @Date 2020-08-14 10:29 上午
 * @Description 演示获取class对象
 * 类加载的时机，使用到的时候再去加载
 */
public class GetDemo {
    /**
     * Class对象的三种获取方式
     *  1.
     */
    @Test
    public void demo1() throws ClassNotFoundException{
        //以字符串为例

        //1  类的class属性
        Class<String> class1 = String.class;

        //2  调用对象的getClass方法
        String s1 = "xxx";
        Class<? extends String> class2 = s1.getClass();

        //3 Class.forName("类的全路径")
        Class<?> class3 =  Class.forName("java.lang.String");

        System.out.println(class1); //class java.lang.String
        System.out.println(class1 == class2);//true
        System.out.println(class2 == class3);//true 因此三种方法一样  用一个就好



    }


    /**
     * 演示获取类的信息
     *
     */
    @Test
    public void demo2(){

        //获取Class对象
        Class<String> stringClass = String.class;

        String name = stringClass.getName();
        System.out.println("class的名字"+name); //class的名字java.lang.String

        Package aPackage = stringClass.getPackage();
        System.out.println("包的名字"+aPackage.getName()); //包的名字java.lang

        //获取类的修饰符
        int modifiers = stringClass.getModifiers();
        System.out.println("类饿修饰符"+modifiers); //类饿修饰符17

        stringClass.getAnnotations();//类上的注解
        stringClass.getInterfaces();//获取接口
        stringClass.getSuperclass();//获取继承关系
    }

    /**
     * 演示创建对象
     * newInstance 调用的是类的无参构造方法，一般来说会给类提供无餐构造方法
     */
    @Test
    public void demo3() throws IllegalAccessException, InstantiationException {
        Class<String> stringClass = String.class;
        String s = stringClass.newInstance();
        System.out.println("创建的String是："+s);

    }

    /**
     * Class对象和Instanceof的区别
     */
    @Test
    public void demo4(){
        Number number = 1;
        Integer integer = 10;

        Class<? extends Number> numberClass = number.getClass();
        Class<? extends Integer> integerClass = integer.getClass();
        System.out.println(numberClass == integerClass); //true

    }


    @Test
    public void demo5() throws NoSuchFieldException {
        Son son = new Son();
        Class<? extends Son> sonClass = son.getClass();
//        sonClass.getDeclaredField(name);//获取单个字段
//        sonClass.getDeclaredFields();//获取多个字段
//        sonClass.getField(name);//获取单个字段
//        sonClass.getField();//获取多个字段

        Field[] fields = sonClass.getFields();
        for(Field field : fields){
            System.out.println(field.getName()); //拿到的是父类和自己的非私有变量
        }
        System.out.println("==============");

        Field[] declareFields = sonClass.getDeclaredFields(); //拿到的是自己声明的所有字段
        for(Field field:declareFields){
            System.out.println(field.getName());
        }

        System.out.println("=============");
        Field field = sonClass.getField("desc");
        System.out.println(field.getName());

    }

    //给字段赋值
    @Test
    public void demo6() throws Exception {
        Son son = new Son();
        Class<? extends Son> sonClass = son.getClass();

        Field ageField = sonClass.getDeclaredField("age");
        // 设置值
        ageField.set(son, 30); // obj：对象   value：值
        // 取值
        int age = (int)ageField.get(son); // 接收取值的对象
        System.out.println(age);

        Field nameField = sonClass.getDeclaredField("sonName");
        nameField.setAccessible(true); // 默认是false
        nameField.set(son, "son的新名字");
        System.out.println(nameField.get(son));
    }
    @Test
    public void demo7(){
        Integer integer = 123;
        System.out.println(integer instanceof Integer);//true
        System.out.println(integer instanceof Number); //true


        Class<Integer> integerClass = Integer.class;
        Class<Number> numberClass = Number.class;
        //System.out.println(integerClass == numberClass);  //class 严格对比

    }


    @Test
    public void demo8() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String string = "123";
        Class<? extends String> stringClass = string.getClass();
//        //获取自身的方法，所有的
//        stringClass.getDeclareMethod(name,parameterTypes);
//        stringClass.getDeclaredMethods();
//        //获取自身和继承过来的，获取非私有
//        stringClass.getMethod(name,parameterTypes);
//        stringClass.getMethods();
        Method method = stringClass.getDeclaredMethod("charAt",int.class);
//        Object object=method.invoke(stringClass,int.class);
//        System.out.println(object);
        System.out.println(method.getName());

        Method method1 = stringClass.getDeclaredMethod("substring", int.class, int.class);
        System.out.println(method1.getName());

        Method method2 = stringClass.getDeclaredMethod("indexOfSupplementary", int.class, int.class);
        System.out.println(method2.getName());

        //getMethod不能获取私有方法，错误的，
//        Method method3 = stringClass.getMethod("indexOfSupplementary", int.class, int.class);//报错
//        System.out.println(method3.getName());

        Method method4 = stringClass.getMethod("substring", int.class);
        System.out.println(method4.getName());

    }

    /**
     * 方法的调用
     * 以String 为例
     */
    @Test
    public void demo9() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String string= "123456789";
        Class<? extends String> stringClass = string.getClass();
        //获取方法
        Method method = stringClass.getDeclaredMethod("substring", int.class);
        //调用方法
        Object result = method.invoke(string,5);//调用方法的obj：调用方法的对象   args：参数    返回：method方法执行的返回和值
        System.out.println("字符串截取的结果是"+result);

        //获取方法
        Method method2 = stringClass.getDeclaredMethod("substring", int.class, int.class);
        //调用方法
        Object object = method2.invoke(string,5,8);
        System.out.println("字符串截取的结果是"+object);


        /**
         * 由private 修饰的方法
         */
        Class<Son> sonClass = Son.class;
        Method method3 = sonClass.getDeclaredMethod("sayHello", String.class, int.class);
        Son son = new Son();
        method3.setAccessible(true);//访问修饰权限  默认是false，当方法为私有时需要改为true
        method3.invoke(son,"java",20);//执行方法


        /**
         * 安全执行方法
         *   1、使用getMethod
         *   2、判断你的访问修饰权限
         */

        boolean isAccessible = method3.getModifiers() == Modifier.PRIVATE;
        if(isAccessible){
            method3.setAccessible(true);
        }
        method3.invoke(son,"JavScript",20);

    }

    /**
     * 静态方法的使用
     */
    @Test
    public void demo10() throws Exception{
        Class<String> stringClass = String.class;
        //获取方法
        Method method = stringClass.getDeclaredMethod("valueOf", int.class);
        if(method.isAccessible()){
            method.setAccessible(true);
        }
        //静态方法调用
        Object o = method.invoke(null,123);//传递一个null  表面静态方法
        System.out.println("调用静态方法的执行结果为"+o);//调用静态方法的执行结果为123

    }

    /**
     * 演示构造方法的使用
     */
    @Test
    public void demo11() throws  Exception{

        Class<Son> sonClass = Son.class;
        /**
         * Declared:可以获取自己的所有的构造方法
         * 不带Declared：可以获取的是父类和自己的所有的非私有的构造方法
         */
//        sonClass.getDeclaredConstructor(parameterTypes);
//        sonClass.getDeclaredConstructors();
//        sonClass.getConstructor(parameterTypes);
//        sonClass.getConstructors();

        //public Son(String name,int age)
        Constructor<Son> declaredConstructor = sonClass.getDeclaredConstructor(String.class, int.class);
        Son son =declaredConstructor.newInstance("java",11);
        System.out.println(son.getSonName()+" "+son.getAge());




    }


    @Test
    public void te(){
//        byte a;
//        int b, c, d;
//        a = 5;
//        b = a += a -= a *= a++;
//        c = b *= b += b += --b;
//        d = c + 2;
//        System.out.println(d > b ? a : c);

        byte b = 'a';
        char c = 97;
        System.out.println(c);



    }


}
